﻿//
// Copyright 2008-2011 by Burt Harris
// Licensed under the Microsoft Public License (Ms-PL)
// See: http://www.codeplex.com/yaml/license
//

using System;
using System.Collections;
using System.Configuration;
using System.Diagnostics.Contracts;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace YaTools.Yaml.UnitTests
{
    /// <summary>
    ///This is a test class for TaggedObjectSinkTest and is intended
    ///to contain all TaggedObjectSinkTest Unit Tests
    ///</summary>
    [TestClass]
    [DeploymentItem(@"CoreUnitTest\Yaml_1.2\")]
    [DeploymentItem(@"CoreUnitTest\Other\")]
    public class TaggedObjectSinkTest
    {
        // ReSharper disable InconsistentNaming
        public TestContext TestContext { get; set; }

        [TestMethod]
        public void ObjAbc()
        {
            var expected = new ArrayList
                               {
                                   "a",
                                   "b",
                                   "c"
                               };
            var actual = YamlLanguage.StringTo<ICollection>(
                "[a, b, c]");
            CollectionAssert.AreEqual(expected, actual);
        }

        [TestMethod]
        [Ignore] // Conversion to ITaggedObject not working at this point
        public void UntaggedString1()
        {
            const string value = "hello YAML";
            var actual = YamlLanguage.StringTo<ITaggedObject>(value);

            Assert.IsInstanceOfType(actual, typeof (TaggedScalar));
            Assert.AreEqual(Tag.String, actual.Tag);
            Assert.AreEqual(value, actual.ToString());
            Assert.AreEqual(1, actual.Count);
        }

        [TestMethod]
        public void UntaggedString2()
        {
            const string expected = "hello YAML";
            const string value = "'hello YAML'";
            var actual = YamlLanguage.StringTo<string>(value);

            Assert.IsInstanceOfType(actual, typeof (string));
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Anchor()
        {
            var actual = YamlLanguage.StringTo<ArrayList>(
                "&foo [ one, &two two, three, *two ]");

            Console.WriteLine("Actual:");
            try
            {
                new Dump().Serialize(Console.Out, actual);
            }
            catch (Exception ex)
            {
                //
                // Wrapping it in an AssertFailedException makes the error message easier to see in the Test Results window...
                // rather than saying "Test method bla.bla.bla threw exception:"
                //
                throw new AssertFailedException(ex.Message, ex);
            }

            Contract.Assume(actual.Count >= 4);
            Assert.AreEqual("two", actual[3].ToString());
            CollectionAssert.AreEqual(new ArrayList {"one", "two", "three", "two"}, actual);
        }

        [TestMethod]
        public void RecuriveAnchor()
        {
            var actual = YamlLanguage.StringTo<ArrayList>(
                "&foo [ one, &two two, three, *foo ]");
            Contract.Assume(actual.Count >= 4);
            Assert.IsInstanceOfType(actual[3], typeof (ArrayList));
            Assert.AreEqual(actual, actual[3]);
        }

        [TestMethod]
        public void NoLiteral() // For workitem 9871
        {
            var list = new ArrayList
                           {
                               "a little string",
                               "A multi-line string with a '\\' (backslash)\nthat might get written out\nusing a literal",
                               "the last string"
                           };

            string s;
            try
            {
                s = new Dump().ToString(list);
            }
            catch (Exception ex)
            {
                throw new AssertFailedException(ex.Message, ex);
            }

            Console.WriteLine(s);

            var r = YamlLanguage.StringTo<object>(s);
            CollectionAssert.AreEqual(list, (IList) r);
        }


        public void ExampleTest(string prefix)
        {
            string fileB = prefix + ".b.yaml";
            string fileA = prefix + ".a.yaml";

            var resultB = YamlLanguage.FileTo<object>(fileB);
            var resultA = YamlLanguage.FileTo<object>(fileA);

            DeepAssert.AreEqual(resultB, resultA);
        }

        [TestMethod]
        [Timeout(60000)]
        public void Workitem9840()
        {
            Contract.Assume(TestContext.TestLogsDir != null);

            // this generates a big narly yaml file throug serialization

            string path = Path.Combine(TestContext.TestLogsDir,
                                       TestContext.TestName + ".yaml");

            TestContext.WriteLine("{0}", path);
            //TestContext.AddResultFile(path);

            object value = ConfigurationManager.OpenExeConfiguration(
                ConfigurationUserLevel.None);

            using (TextWriter writer = File.CreateText(path))
            {
                try
                {
                    new Dump().Serialize((writer), value);
                }
                catch (Exception ex)
                {
                    throw new AssertFailedException(ex.Message, ex);
                }
            }

            // make sure it deserializes without exceptions...
            YamlLanguage.FileTo<object>(path);
        }


        [TestMethod]
        public void Example2_01()
        {
            ExampleTest("02.01");
        }

        [TestMethod]
        public void Example2_02()
        {
            ExampleTest("02.02");
        }

        [TestMethod]
        public void Example2_03()
        {
            ExampleTest("02.03");
        }

        [TestMethod]
        public void Example2_04()
        {
            ExampleTest("02.04");
        }

        [TestMethod]
        public void Example2_05()
        {
            ExampleTest("02.05");
        }


        [TestMethod]
        public void Example2_06()
        {
            ExampleTest("02.06");
        }

        [TestMethod]
        public void Example2_07()
        {
            ExampleTest("02.07");
        }

        [TestMethod]
        public void Example2_08()
        {
            ExampleTest("02.08");
        }

        [TestMethod]
        public void Example2_09()
        {
            ExampleTest("02.09");
        }

        [TestMethod]
        public void Example2_10()
        {
            ExampleTest("02.10");
        }

        [TestMethod]
        public void Example2_11()
        {
            ExampleTest("02.11");
        }

        [TestMethod]
        public void Example2_12()
        {
            ExampleTest("02.12");
        }

        [TestMethod]
        public void Example2_13()
        {
            ExampleTest("02.13");
        }

        [TestMethod]
        public void Example2_14()
        {
            ExampleTest("02.14");
        }

        [TestMethod]
        public void Example2_15()
        {
            ExampleTest("02.15");
        }


        [TestMethod]
        public void Example2_16()
        {
            ExampleTest("02.16");
        }

        [TestMethod]
        public void Example2_17()
        {
            ExampleTest("02.17");
        }

        [TestMethod]
        public void Example2_18()
        {
            ExampleTest("02.18");
        }

        [TestMethod]
        public void Example2_19()
        {
            ExampleTest("02.19");
        }

        [TestMethod]
        public void Example2_20()
        {
            ExampleTest("02.20");
        }

        [TestMethod]
        public void Example2_21()
        {
            ExampleTest("02.21");
        }

        [TestMethod]
        public void Example2_22()
        {
            ExampleTest("02.22");
        }

        [TestMethod]
        public void Example2_23()
        {
            ExampleTest("02.23");
        }

        [TestMethod]
        public void Example2_24()
        {
            ExampleTest("02.24");
        }

        [TestMethod]
        public void Example2_25()
        {
            ExampleTest("02.25");
        }


        [TestMethod]
        public void Example2_26()
        {
            ExampleTest("02.26");
        }

        [TestMethod]
        public void Example2_27()
        {
            ExampleTest("02.27");
        }

        [TestMethod]
        public void Example2_28()
        {
            ExampleTest("02.28");
        }

        // ReSharper restore InconsistentNaming
    }
}